const {QueryTypes, Op, Transaction} = require('sequelize');
const seq = require('../db/seq');
const {User, Message, Site, Match} = require('../model');
const jwt = require('jsonwebtoken');
const {secretKey} = require('../jwt/index');
const moment = require('moment');

let userService = {
    //添加用户
    async addUser(username, password) {
        let findResult = await userService.findUser({username});
        if (!findResult) {
            const result = await User.create({
                username,
                password
            });
            return result.dataValues;
        } else {
            return findResult.dataValues;
        }
    },
    //查找单个用户
    async findUser(params) {
        return await User.findOne({
            where: {
                ...params
            },
            attributes: {exclude: ['password']}
        });
    },
    //注册用户
    async register(params, ctx) {
        let findResult = await userService.findUser({username: params.username});
        if (!findResult) {
            const result = await User.create({
                username: params.username,
                password: params.password
            });
            if (result) {
                const token = await userService.generateToken(result.dataValues);
                ctx.session[token] = result;
                return {code: 1, msg: '注册成功', data: {...result.dataValues, token}};
            } else {
                return {code: 0, msg: '注册失败'};
            }
        } else {
            return {code: 0, msg: '该用户已注册'};
        }
    },
    //用户登录
    async login(params, ctx) {
        let findResult = await userService.findUser({username: params.username, password: params.password});
        if (findResult) {
            const token = await userService.generateToken(findResult.dataValues);
            ctx.session[token] = findResult;
            return {code: 1, msg: '登录成功', data: {...findResult.dataValues, token}};
        } else {
            return {code: 0, msg: '该账号未注册'};
        }
    },
    //生成token
    generateToken(userData) {
        const payload = {
            id: userData.id,
            username: userData.username,
            time: Date.now()
        };
        return jwt.sign(payload, secretKey);
    },
    //获取未读消息数
    async getNewMessageCount(id) {
        return await Message.count({
            where: {
                toUserId: id,
                isRead: 0
            }
        });
    },

    //获取聊天列表
    async getChatList({id = 192}) {
        try {
            const sql = `select a.*,IFNULL(b.count,0) as count from (SELECT
* 
FROM
(
SELECT
* 
FROM
message 
WHERE
createdAt IN (
SELECT
MAX( createdAt ) 
FROM
message 
WHERE
toUserId = ${id} 
OR fromUserId = ${id} 
GROUP BY
CONCAT(
IF
( fromUserId > toUserId, fromUserId, toUserId ),
IF
( fromUserId < toUserId, fromUserId, toUserId ))) 
AND ( toUserId = ${id} OR fromUserId = ${id} ) 
ORDER BY
id DESC 
) c ORDER BY
c.createdAt DESC) a  LEFT JOIN (select *,count(*) as count from message where toUserId=${id} and isRead=0 group by fromUserId order by createdAt desc) b
ON (a.fromUserId=b.fromUserId and a.toUserId=b.toUserId) OR (a.fromUserId=b.toUserId and a.toUserId=b.fromUserId) ORDER BY a.createdAt DESC`;
            let list = await seq.query(sql, {type: QueryTypes.SELECT});
            for (let i = 0; i < list.length; i++) {
                let item = list[i];
                let searchId = item.fromUserId === Number(id) ? item.toUserId : item.fromUserId;
                list[i]['userInfo'] = await userService.findUser({id: searchId});
            }
            return {code: 1, msg: '查找成功', data: {list}};
        } catch (e) {
            return {code: 0, msg: '查找失败', data: {list: []}};
        }

    },

    //获取指定用户的聊天记录
    async getMessageList(currentUserId, userId, offset) {
        try {
            //当offset为0时，将未读消息改为已读
            if (offset === 0) {
                await Message.update({isRead: 1}, {
                    where: {
                        fromUserId: userId,
                        toUserId: currentUserId,
                        isRead: 0
                    }
                });
            }
            return await Message.findAll({
                where: {
                    [Op.or]: [
                        {
                            fromUserId: currentUserId,
                            toUserId: userId
                        },
                        {
                            fromUserId: userId,
                            toUserId: currentUserId
                        }
                    ]
                },
                order: [
                    ['createdAt', 'DESC']
                ],
                offset,
                limit: 20
            });
        } catch (err) {
            return [];
        }

    },
    //添加新消息
    async addNewMessage(data) {
        try {
            data['isRead'] = 0;
            data['isSend'] = 0;
            const result = await Message.create(data);
            result.dataValues['createdAt'] = moment(result.dataValues['createdAt']).utcOffset("+08:00").format('YYYY-MM-DD HH:mm:ss');
            if (result) {
                return {code: 1, msg: 'success', data: result};
            } else {
                return {code: 0, msg: 'fail'};
            }
        } catch (e) {
            return {code: 0, msg: e.message};
        }
    },
    //更新消息为已读
    async updateNewMessage(data) {
        try {
            const result = await Message.update({isRead: 1}, {
                where: {
                    fromUserId: data.fromUserId,
                    toUserId: data.toUserId,
                }
            });
            if (result) {
                return {code: 1, msg: 'success', data: result};
            } else {
                return {code: 0, msg: 'fail'};
            }
        } catch (e) {
            return {code: 0, msg: e.message};
        }
    },
    //连接客服
    async connectService(data) {
        try {
            const site = await Site.findOne({where: {token: data.siteToken}});
            let serviceUser = null;
            if (site) {
                serviceUser = await userService.findUser({siteId: site.id, type: 1});
            }
            if (site && serviceUser) {
                const findUser = await userService.findUser({
                    username: data.visitorId,
                    siteId: site.id,
                    type: 2
                });
                if (!findUser) {
                    let user = await User.create({
                        username: data.visitorId,
                        password: '',
                        siteId: site.id,
                        type: 2
                    });
                    if (user) {
                        return {code: 1, msg: 'success', data: {site, serviceUser, user}};
                    } else {
                        return {code: 0, msg: '连接客服失败'};
                    }
                } else {
                    return {code: 1, msg: 'success', data: {site, serviceUser, user: findUser}};
                }

            } else {
                return {code: 0, msg: '未找到相关网站客服，请确认siteToken是否有误'};
            }
        } catch (e) {
            return {code: 0, msg: '连接客服失败'};
        }
    },

    //获取网站信息
    async getSite(ctx) {
        try {
            let token = ctx.headers['authorization'];
            let userInfo = ctx.session[token];
            let siteInfo = await Site.findOne({
                where: {
                    id: userInfo['siteId']
                }
            });
            if (siteInfo) {
                return {code: 1, msg: 'success', data: {siteInfo}};
            } else {
                return {code: 0, msg: '未找到相关网站'};
            }
        } catch (err) {
            return {code: 0, msg: err.message};
        }

    },
    //保存网站信息
    async editSite(data, ctx) {
        try {
            let token = ctx.headers['authorization'];
            let userInfo = ctx.session[token];
            //data['token'] = token;
            let siteInfo = await Site.update(data, {
                where: {
                    id: userInfo['siteId']
                }
            });
            if (siteInfo) {
                return {code: 1, msg: '修改成功'};
            } else {
                return {code: 0, msg: '修改失败'};
            }
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //用户列表
    async getUserList(ctx) {
        try {
            const params = ctx.request.query;
            let token = ctx.headers['authorization'];
            let userInfo = ctx.session[token];
            const where = {
                id: {
                    [Op.notIn]: [userInfo['id']]
                }
            };
            if (params.name) {
                where['name'] = {[Op.like]: `%${params.name}%`};
            }
            let {count, rows} = await User.findAndCountAll({
                where,
                attributes: {exclude: ['password']},
                order: [
                    ['createdAt', 'DESC']
                ],
                offset: (params.page - 1) * 10,
                limit: 10
            });
            return {code: 1, msg: 'success', data: {count, list: rows}};
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //用户详情
    async getUserDetail(ctx) {
        try {
            let token = ctx.headers['authorization'];
            let userInfo = ctx.session[token];
            let userDetail = await User.findOne({
                where: {
                    id: userInfo['id']
                },
                attributes: {exclude: ['password']}
            });
            if (userDetail) {
                return {code: 1, msg: 'success', data: {userDetail}};
            } else {
                return {code: 0, msg: '未找到相关用户'};
            }
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //编辑用户信息
    async editUserInfo(data, ctx) {
        try {
            let token = ctx.headers['authorization'];
            let userInfo = ctx.session[token];
            let userDetail = await User.update(data, {
                where: {
                    id: userInfo['id']
                },
                attributes: {exclude: ['password']}
            });
            if (userDetail) {
                return {code: 1, msg: 'success'};
            } else {
                return {code: 0, msg: '未找到相关用户'};
            }
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //比赛列表
    async getMatchList(ctx) {
        try {
            const params = ctx.request.query;
            let token = ctx.headers['authorization'];
            let userInfo = ctx.session[token];
            const where = {
                [Op.or]: [{initiatorId: userInfo['id']}, {recipientId: userInfo['id']}]
            };
            if (params.state) {
                where['state'] = params.state;
            }
            let {count, rows} = await Match.findAndCountAll({
                where,
                order: [
                    ['createdAt', 'DESC']
                ],
                offset: (params.page - 1) * 10,
                limit: 10
            });
            return {code: 1, msg: 'success', data: {count, list: rows}};
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //排行榜
    async getRankingList() {
        try {
            let list = await User.findAll({
                attributes: {exclude: ['password']},
                order: [
                    ['score', 'DESC']
                ],
                limit: 30
            });
            return {code: 1, msg: 'success', data: {list}};
        } catch (err) {
            return {code: 0, msg: err.message, data: {list: []}};
        }
    },
    //判断用户是否空闲
    async checkUserIsFree(id) {
        try {
            let result = await Match.findOne({
                where: {
                    [Op.or]: [{initiatorId: id}, {recipientId: id}],
                    state: 0
                }
            });
            if (result) {
                return {code: 0, msg: '用户正在比赛'};
            } else {
                return {code: 1, msg: ''};
            }
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //创建比赛
    async createMath(data) {
        try {
            data['state'] = 0;
            let result = await Match.create(data);
            if (result) {
                return {code: 1, msg: '创建成功'};
            } else {
                return {code: 0, msg: '创建失败'};
            }
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //获取比赛数据
    async getChess(ctx) {
        try {
            let token = ctx.headers['authorization'];
            let userInfo = ctx.session[token];
            const where = {
                [Op.or]: [{initiatorId: userInfo['id']}, {recipientId: userInfo['id']}]
            };
            where['state'] = 0;
            let result = await Match.findOne({
                where
            });
            if (result) {
                let createdAtTime = new Date(result['createdAt']).getTime();
                let currentTime = Date.now();
                let matchTimes = currentTime - createdAtTime;
                if (matchTimes > 20 * 60 * 1000) {
                    await result.update({state: 1, winnerId: -1});
                    return {code: 0, msg: '比赛超时，平局'};
                } else {
                    result.dataValues['camp'] = result.dataValues['initiatorId'] == userInfo['id'] ? 2 : 1;
                    result.dataValues['enemy'] = result.dataValues['initiatorId'] == userInfo['id'] ? result.dataValues['recipientId'] : result.dataValues['initiatorId'];
                    result.dataValues['enemyUserInfo'] = await userService.findUser({id: result.dataValues['enemy']});
                    result.dataValues['matchTimes'] = 20 * 60 * 1000 - matchTimes;
                    return {code: 1, msg: 'success', data: {chess: result}};
                }
            } else {
                return {code: 0, msg: '未找到比赛'};
            }
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //放弃比赛
    async giveUpChallenge(userId) {
        try {
            await seq.transaction({isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE}, async (t) => {
                let list = await Match.findAll({
                    where: {
                        [Op.or]: [{initiatorId: userId}, {recipientId: userId}],
                        state: 0
                    },
                    for: 'update',
                    transaction: t
                });
                for (let i = 0; i < list.length; i++) {
                    let match = list[i];
                    let data = {};
                    if (match.dataValues['initiatorId'] === userId) {
                        data = {winnerId: match.dataValues['recipientId'], state: 1};
                    } else {
                        data = {winnerId: match.dataValues['initiatorId'], state: 1};
                    }
                    await match.update(data, {where: {state: 0}, transaction: t});
                    await User.increment({score: 10}, {where: {id: data['winnerId']}, transaction: t});
                    await User.increment({score: -10}, {where: {id: userId}, transaction: t});
                }
            });
            return {code: 1, msg: ''};
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //保存比赛数据
    async saveMatchData(data) {
        try {
            await seq.transaction({isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE}, async (t) => {
                if (data['isFinish']) {
                    await Match.update({chessData: null, state: 1, winnerId: data['winnerId']}, {
                        where: {id: data['matchId'], state: 0},
                        transaction: t
                    });
                    await User.increment({score: 10}, {where: {id: data['winnerId']}, transaction: t});
                    const loseId = data['winnerId'] === data['enemy'] ? data['currentUserId'] : data['enemy'];
                    await User.increment({score: -10}, {where: {id: loseId}, transaction: t});
                } else {
                    await Match.update({chessData: data.chessData}, {where: {id: data['matchId']}, transaction: t});
                }
            });
            return {code: 1, msg: ''};
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //平局
    async matchDraw(data) {
        try {
            await seq.transaction({isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE}, async (t) => {
                await Match.update({chessData: null, state: 1, winnerId: 0}, {
                    where: {id: data['matchId']},
                    transaction: t
                });
            });
            return {code: 1, msg: ''};
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    },
    //主动认输
    async admitDefeat(data) {
        try {
            await seq.transaction({isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE}, async (t) => {
                await Match.update({chessData: null, state: 1, winnerId: data['toUserId']}, {
                    where: {id: data['matchId'], state: 0},
                    transaction: t
                });
                await User.increment({score: 10}, {where: {id: data['toUserId']}, transaction: t});
                await User.increment({score: -10}, {where: {id: data['currentUserId']}, transaction: t});
            });
            return {code: 1, msg: ''};
        } catch (err) {
            return {code: 0, msg: err.message};
        }
    }
};
module.exports = userService;